"""
图像显示组件
负责图像的加载、显示和格式转换
"""

import cv2
import numpy as np
from pathlib import Path
from PySide6.QtWidgets import QWidget, QVBoxLayout, QLabel, QScrollArea
from PySide6.QtCore import Qt, Signal
from PySide6.QtGui import QPixmap, QImage

from src.config import config
from src.utils.logger import app_logger


class ImageDisplayWidget(QWidget):
    """
    图像显示组件类
    
    用途：
    - 显示原始图像和处理结果
    - 支持图像缩放和滚动
    - 提供图像格式转换功能
    
    信号：
    - image_loaded: 图像加载完成时发出
    """
    
    image_loaded = Signal(str)  # 图像路径
    
    def __init__(self, parent=None):
        super().__init__(parent)
        self.current_image_path = None
        self.setup_ui()
    
    def setup_ui(self):
        """
        设置用户界面
        """
        layout = QVBoxLayout(self)
        
        # 创建滚动区域
        self.scroll_area = QScrollArea()
        self.scroll_area.setWidgetResizable(True)
        self.scroll_area.setAlignment(Qt.AlignCenter)
        
        # 创建图像标签
        self.image_label = QLabel()
        self.image_label.setAlignment(Qt.AlignCenter)
        
        # 从配置读取显示尺寸
        display_size = config.get('gui.image_display_size')
        self.image_label.setMinimumSize(*display_size)
        
        # 从配置读取边框样式
        border_style = config.get('gui.styles.border_style')
        self.image_label.setStyleSheet(f"border: {border_style};")
        self.image_label.setText("请选择图像文件")
        
        self.scroll_area.setWidget(self.image_label)
        layout.addWidget(self.scroll_area)
    
    def load_image(self, image_path: str) -> bool:
        """
        加载并显示图像
        
        参数：
            image_path (str): 图像文件路径
            
        返回值：
            bool: 是否加载成功
        """
        try:
            # 读取图像
            image = cv2.imread(image_path)
            if image is None:
                app_logger.error(f"无法加载图像: {image_path}")
                self.image_label.setText("图像加载失败")
                return False
            
            # 转换为RGB格式
            image_rgb = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
            
            # 调整图像大小以适应显示
            display_image = self._resize_for_display(image_rgb)
            
            # 转换为QPixmap并显示
            pixmap = self._array_to_pixmap(display_image)
            self.image_label.setPixmap(pixmap)
            self.image_label.setScaledContents(True)
            
            self.current_image_path = image_path
            self.image_loaded.emit(image_path)
            
            app_logger.info(f"图像加载成功: {Path(image_path).name}")
            return True
            
        except Exception as e:
            app_logger.error(f"加载图像失败: {e}")
            self.image_label.setText("图像加载失败")
            return False
    
    def display_result_image(self, image_array: np.ndarray) -> bool:
        """
        显示处理结果图像
        
        参数：
            image_array (np.ndarray): 图像数组（BGR格式）
            
        返回值：
            bool: 是否显示成功
        """
        try:
            # 转换为RGB格式
            if len(image_array.shape) == 3 and image_array.shape[2] == 3:
                image_rgb = cv2.cvtColor(image_array, cv2.COLOR_BGR2RGB)
            else:
                image_rgb = image_array
            
            # 调整图像大小
            display_image = self._resize_for_display(image_rgb)
            
            # 转换为QPixmap并显示
            pixmap = self._array_to_pixmap(display_image)
            self.image_label.setPixmap(pixmap)
            self.image_label.setScaledContents(True)
            
            return True
            
        except Exception as e:
            app_logger.error(f"显示结果图像失败: {e}")
            return False
    
    def clear_image(self):
        """
        清除当前显示的图像
        """
        self.image_label.clear()
        self.image_label.setText("请选择图像文件")
        self.current_image_path = None
    
    def _resize_for_display(self, image: np.ndarray) -> np.ndarray:
        """
        调整图像尺寸以适应显示
        
        参数：
            image (np.ndarray): 输入图像
            
        返回值：
            np.ndarray: 调整后的图像
        """
        height, width = image.shape[:2]
        max_size = config.get('image_processing.display_max_size')
        
        # 如果图像尺寸已经小于最大尺寸，直接返回
        if max(height, width) <= max_size:
            return image
        
        # 计算缩放比例
        if height > width:
            new_height = max_size
            new_width = int(width * max_size / height)
        else:
            new_width = max_size
            new_height = int(height * max_size / width)
        
        resized = cv2.resize(image, (new_width, new_height), interpolation=cv2.INTER_AREA)
        app_logger.debug(f"图像尺寸调整: {width}x{height} -> {new_width}x{new_height}")
        
        return resized
    
    def _array_to_pixmap(self, image_array: np.ndarray) -> QPixmap:
        """
        将numpy数组转换为QPixmap
        
        参数：
            image_array (np.ndarray): 图像数组（RGB格式）
            
        返回值：
            QPixmap: Qt图像对象
        """
        height, width, channel = image_array.shape
        bytes_per_line = 3 * width
        
        q_image = QImage(
            image_array.data, 
            width, 
            height, 
            bytes_per_line, 
            QImage.Format_RGB888
        )
        
        return QPixmap.fromImage(q_image)
    
    def get_current_image_path(self) -> str:
        """
        获取当前显示的图像路径
        
        返回值：
            str: 图像路径，如果没有则返回None
        """
        return self.current_image_path 